//
//  ScrollableImageView.swift
//  CooImage
//
//  Created by jerry on 2025/8/16.
//

import SwiftUI

struct ScrollableImageView: NSViewRepresentable {
    let image: NSImage
    @Binding var currentScale: CGFloat
    @Binding var lastScale: CGFloat
    var rotationAngle: Double = 0.0
    @State private var lastImageSize: CGSize = .zero
    
    func makeNSView(context: Context) -> NSScrollView {
        let scrollView = ZoomableScrollView(
            currentScaleBinding: $currentScale,
            lastScaleBinding: $lastScale
        )
        
        let imageView = NSImageView()
        imageView.image = image
        imageView.imageScaling = .scaleProportionallyUpOrDown
        
        // 设置滚动视图属性，使图片居中
        scrollView.documentView = imageView
        scrollView.contentView.postsFrameChangedNotifications = true
        scrollView.contentView.postsBoundsChangedNotifications = true
        scrollView.allowsMagnification = true
        scrollView.minMagnification = 0.1
        scrollView.maxMagnification = 10.0
        
        // 设置滚动视图的背景色
        scrollView.backgroundColor = NSColor.clear
        scrollView.drawsBackground = false
        
        // 延迟计算适合的缩放比例，等待视图布局完成
        DispatchQueue.main.async {
            self.fitImageToView(scrollView: scrollView, imageView: imageView)
        }
        
        return scrollView
    }
    
    func updateNSView(_ nsView: NSScrollView, context: Context) {
        if let imageView = nsView.documentView as? NSImageView {
            let oldImage = imageView.image
            imageView.image = image
            
            // 检查是否是新图片
            let isNewImage = oldImage != image || lastImageSize != image.size
            if isNewImage {
                lastImageSize = image.size
                // 新图片时自动适应界面大小
                DispatchQueue.main.async {
                    self.fitImageToView(scrollView: nsView, imageView: imageView)
                }
            }
            
            // 更新图片大小和旋转
            if let image = imageView.image {
                // 应用旋转
                let rotatedImage = rotateImage(image: image, byDegrees: rotationAngle)
                imageView.image = rotatedImage
                
                // 更新图片大小
                let imageSize = CGSize(
                    width: rotatedImage.size.width * currentScale,
                    height: rotatedImage.size.height * currentScale
                )
                imageView.frame.size = imageSize
                
                // 获取滚动视图的可见区域
                let clipView = nsView.contentView
                let visibleRect = clipView.documentVisibleRect
                
                // 计算图片在视图中的位置，使其居中
                let newX = max(0, (imageSize.width - visibleRect.width) / 2)
                let newY = max(0, (imageSize.height - visibleRect.height) / 2)
                
                // 设置图片位置
                clipView.scroll(to: CGPoint(x: newX, y: newY))
                
                // 设置图片在滚动视图中的对齐方式
                nsView.horizontalScrollElasticity = .none
                nsView.verticalScrollElasticity = .none
                
                // 如果图片小于视图，则居中显示
                if imageSize.width < visibleRect.width || imageSize.height < visibleRect.height {
                    // 计算居中位置
                    let centerX = max(0, (visibleRect.width - imageSize.width) / 2)
                    let centerY = max(0, (visibleRect.height - imageSize.height) / 2)
                    
                    // 设置图片位置
                    imageView.frame.origin = CGPoint(x: centerX, y: centerY)
                }
            }
        }
    }
    
    // 计算适合界面大小的缩放比例
    private func fitImageToView(scrollView: NSScrollView, imageView: NSImageView) {
        guard let image = imageView.image else { return }
        
        let scrollViewSize = scrollView.contentView.bounds.size
        let imageSize = image.size
        
        // 如果滚动视图还没有大小，延迟执行
        if scrollViewSize.width <= 0 || scrollViewSize.height <= 0 {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                self.fitImageToView(scrollView: scrollView, imageView: imageView)
            }
            return
        }
        
        // 计算适合的缩放比例
        let scaleX = scrollViewSize.width / imageSize.width
        let scaleY = scrollViewSize.height / imageSize.height
        let fitScale = min(scaleX, scaleY)
        
        // 只有当图片比界面大时才缩小，小图片保持原始大小
        if fitScale < 1.0 {
            // 只在初始状态（缩放为1.0）时自动适应
            if currentScale == 1.0 && lastScale == 1.0 {
                currentScale = fitScale
                lastScale = fitScale
            }
            
            // 更新图片大小
            let scaledSize = CGSize(
                width: imageSize.width * currentScale,
                height: imageSize.height * currentScale
            )
            imageView.frame.size = scaledSize
            
            // 居中显示
            let centerX = max(0, (scrollViewSize.width - scaledSize.width) / 2)
            let centerY = max(0, (scrollViewSize.height - scaledSize.height) / 2)
            imageView.frame.origin = CGPoint(x: centerX, y: centerY)
        } else {
            // 小图片居中显示
            imageView.frame.size = CGSize(width: imageSize.width * currentScale, height: imageSize.height * currentScale)
            let scaledSize = imageView.frame.size
            let centerX = max(0, (scrollViewSize.width - scaledSize.width) / 2)
            let centerY = max(0, (scrollViewSize.height - scaledSize.height) / 2)
            imageView.frame.origin = CGPoint(x: centerX, y: centerY)
        }
    }
    
    // 旋转图片的辅助方法
    private func rotateImage(image: NSImage, byDegrees degrees: Double) -> NSImage {
        if degrees == 0 {
            return image
        }
        
        // 转换为弧度，用于计算
        _ = degrees * .pi / 180.0
        let size = image.size
        
        // 计算旋转后的尺寸
        let newSize: NSSize
        if Int(degrees) % 180 == 0 {
            newSize = size
        } else {
            // 90度或270度旋转，宽高互换
            newSize = NSSize(width: size.height, height: size.width)
        }
        
        // 创建新图片
        let newImage = NSImage(size: newSize)
        
        newImage.lockFocus()
        
        // 设置旋转变换
        let transform = NSAffineTransform()
        transform.translateX(by: newSize.width / 2, yBy: newSize.height / 2)
        transform.rotate(byDegrees: CGFloat(degrees))
        transform.translateX(by: -size.width / 2, yBy: -size.height / 2)
        transform.concat()
        
        // 绘制原图
        image.draw(in: NSRect(x: 0, y: 0, width: size.width, height: size.height),
                  from: NSRect(x: 0, y: 0, width: size.width, height: size.height),
                  operation: .copy,
                  fraction: 1.0)
        
        newImage.unlockFocus()
        
        return newImage
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject {
        var parent: ScrollableImageView
        weak var scrollView: NSScrollView?
        
        init(_ parent: ScrollableImageView) {
            self.parent = parent
        }
        
        @objc func viewBoundsDidChange(_ notification: Notification) {
            // 处理滚动事件
        }
    }
}

class ZoomableScrollView: NSScrollView {
    var currentScaleBinding: Binding<CGFloat>
    var lastScaleBinding: Binding<CGFloat>
    private var magnificationGesture: NSMagnificationGestureRecognizer?
    
    init(currentScaleBinding: Binding<CGFloat>, lastScaleBinding: Binding<CGFloat>) {
        self.currentScaleBinding = currentScaleBinding
        self.lastScaleBinding = lastScaleBinding
        super.init(frame: .zero)
        self.hasVerticalScroller = true
        self.hasHorizontalScroller = true
        self.autohidesScrollers = true
        
        // 添加触摸板缩放手势
        setupGestures()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func setupGestures() {
        // 添加触摸板缩放手势
        let magnification = NSMagnificationGestureRecognizer(target: self, action: #selector(handleMagnification(_:)))
        self.addGestureRecognizer(magnification)
        self.magnificationGesture = magnification
    }
    
    @objc private func handleMagnification(_ gesture: NSMagnificationGestureRecognizer) {
        switch gesture.state {
        case .began:
            // 开始缩放时记录当前比例
            lastScaleBinding.wrappedValue = currentScaleBinding.wrappedValue
        case .changed:
            // 缩放过程中更新比例
            let magnification = gesture.magnification + 1.0
            currentScaleBinding.wrappedValue = lastScaleBinding.wrappedValue * magnification
        case .ended:
            // 缩放结束时更新最终比例
            lastScaleBinding.wrappedValue = currentScaleBinding.wrappedValue
        default:
            break
        }
    }
    
    override func scrollWheel(with event: NSEvent) {
        if event.modifierFlags.contains(.command) {
            // 处理缩放
            let delta = event.deltaY
            let zoomFactor: CGFloat = delta > 0 ? 1.1 : 0.9
            
            // 更新缩放比例
            currentScaleBinding.wrappedValue *= zoomFactor
            lastScaleBinding.wrappedValue = currentScaleBinding.wrappedValue
        } else {
            // 正常滚动
            super.scrollWheel(with: event)
        }
    }
}
